using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.Windows.Forms;

namespace ValidationRuleWriter
{

    /// <summary>
    /// Represents a Windows combo box control that remembers the entries places inside it.
    /// </summary>
    /// <seealso cref="MaximumRememberedValues"/>
    /// <seealso cref="SettingsKey"/>
    /// <seealso cref="SettingsKey"/>
    public class RememberComboBox : ComboBox
    {
        private string settingsKey;
        private int maximumRememberedValues = 10;

        internal sealed class Settings : ApplicationSettingsBase
        {
            internal static Settings GetInstance(string settingsKey)
            {
                if (string.IsNullOrEmpty(settingsKey))
                {
                    throw new ArgumentNullException("settingsKey");
                }
                var settings = (Settings)(Synchronized(new Settings()));
                settings.SettingsKey = settingsKey;
                if (settings.RememberedStrings == null)
                {
                    settings.RememberedStrings = new List<string>();
                }
                return settings;
            }

            [UserScopedSettingAttribute]
            [DebuggerNonUserCode]
            public List<string> RememberedStrings
            {
                get
                {
                    return (List<string>)(this["RememberedStrings"]);
                }
                set
                {
                    this["RememberedStrings"] = value;
                }
            }
        }


		/// <inheritdoc />
        protected override void OnCreateControl()
        {
            base.OnCreateControl();
            if (!DesignMode && (LicenseManager.UsageMode != LicenseUsageMode.Designtime))
            {
                var settings = Settings.GetInstance(settingsKey);
                TrimExcess(settings);
                settings.Save();
                RefreshRememberedItems(settings);
            }
        }


        private void RefreshRememberedItems(Settings settings)
        {
            var rememberedStrings = settings.RememberedStrings;
            Items.Clear();
            for (var index = 0; index < rememberedStrings.Count; index++)
            {
                Items.Add(rememberedStrings[index]);
            }
        }


        /// <summary>
        /// Gets or sets the settings key to use.
        /// </summary>
        public string SettingsKey
        {
            get
            {
                return settingsKey;
            }
            set
            {

                if (!DesignMode && (LicenseManager.UsageMode != LicenseUsageMode.Designtime))
                {
                    if (value == null)
                    {
                        throw new ArgumentNullException("value", "SettingKey may not be null.");
                    }
                    if (value.Length == 0)
                    {
                        throw new ArgumentException("SettingKey may not be empty.", "value");
                    }
                }
                settingsKey = value;
                if (Created)
                {
                    RefreshRememberedItems(Settings.GetInstance(settingsKey));
                }
            }
        }


        /// <summary>
        /// Gets or sets the maximum number of values that are remembered.
        /// </summary>
        public int MaximumRememberedValues
        {
            get
            {
                return maximumRememberedValues;
            }
            set
            {

                if (!DesignMode && (LicenseManager.UsageMode != LicenseUsageMode.Designtime))
                {
                    if (value < 5)
                    {
                        throw new ArgumentOutOfRangeException("value", "MaximumRememberedValues must be at lease 5.");
                    }
                }

                maximumRememberedValues = value;

                if (Created)
                {
                    var settings = Settings.GetInstance(settingsKey);
                    TrimExcess(settings);
                    settings.Save();
                    RefreshRememberedItems(settings);
                }
            }
        }


        private void TrimExcess(Settings settings)
        {
            var rememberedStrings = settings.RememberedStrings;

            while (rememberedStrings.Count > maximumRememberedValues)
            {
                rememberedStrings.RemoveAt(rememberedStrings.Count - 1);
            }
        }


        /// <summary>
        /// Add a value to the history fo remembered values.
        /// </summary>
        /// <param name="value">The value to add.</param>
        public void AddRememberedValue(string value)
        {
            SuspendLayout();
            var temp = Text;

            var settings = Settings.GetInstance(settingsKey);
            var collection = settings.RememberedStrings;
            if (collection.Contains(value))
            {
                collection.Remove(value);
            }
            collection.Insert(0, value);
            TrimExcess(settings);
            settings.Save();
            RefreshRememberedItems(settings);

            Text = temp;
            ResumeLayout();
        }


        /// <summary>
        /// Clear the history of remembered values.
        /// </summary>
        public void ClearRememberedValues()
        {
            Items.Clear();
            var settings = Settings.GetInstance(settingsKey);
            settings.RememberedStrings.Clear();
            settings.Save();
        }
    }
}